<?php
/*  vim: set expandtab shiftwidth=4 softtabstop=4 tabstop=4:    */

class PDO_Mysql extends PDOAbstract implements PDOInterface {

	public function __construct(array $dsn) {
        parent::__construct($dsn);
    }

  /*
   *      Primary public function to execute a query
   *      to the database.
   */
	public function query($sql,$fetchMode=PDO::FETCH_ASSOC) {
		if(!($sth = self::prepare($sql))) throw new Exception('DB Failed [prepare statement initialization failed]');
		if($fetchMode) $sth->setFetchMode($fetchMode);
		$sth->execute();
		while ($row = $sth->fetch()) $res[] = $row;
		if(isset($res) && is_array($res)) {
			if(count($res) > 1) {
				return $res;
			} else {
				return $res[0];
			}
		}
		if($err = $sth->errorInfo()) {
			if(isset($err[1]) && $err[1] > 0) throw new Exception('Query Failed ['.print_r($err,true).']');
		}
		return FALSE;
	}


	/*
	*     Insert Prepare wrapper method
	*  @params: type 2d associative array ('field'=>'val')
	*
	*/
	
	public function insert($table,array $params,$extra = NULL) {
		$sql = 'INSERT INTO '.$table.' ';
		$sql .= "(".implode(",",array_keys($params)) .")";
		$params = self::clean($params);
		$sql .= " VALUES (".implode(",",array_values($params)) .")";
		if(!($stmt = self::prepare($sql))) throw new Exception('DB Failed [prepare statement initialization failed]');
        $stmt->execute();
        $affected = $stmt->rowCount();
        if($affected > 0) {
            return $affected;
        } else {
			if($err = $stmt->errorInfo()) {
				if(isset($err[1]) && $err[1] > 0) throw new Exception('Insert Failed ['.print_r($err,true).'] sql: ['.$sql.']');
			}
			return FALSE;
        }
	}

	
	
    public function update($table,array $params,array $matches) {
    	$matches = self::clean($matches);
        $sql = 'UPDATE '.$table.' SET ';
        $rc = count($params);
        $j = 0;
        foreach ($params as $field => $val) {
            $sql .= ' '.$field.' = :'.$field.' ';
            if(($j+1) < $rc) $sql .= ',';
            $j++;
        }
        $sql .= " WHERE";
        $rc = count($matches);
        $j = 0;
        foreach ($matches as $field => $val) {
            $sql .= " ".$field." = $val ";
            if(($j+1) < $rc) $sql .= 'AND';
            $j++;
        }
        //echo $sql;
        if(!($stmt = self::prepare($sql))) throw new Exception('DB Failed [prepare statement initialization failed]');
        foreach ($params as $field => $val) {
            $stmt->bindValue(':'.$field,$val);
        }
        $stmt->execute();
        $affected = $stmt->rowCount();
        if($affected > 0) {
            return $affected;
        } else {
            if($err = $stmt->errorInfo()) {
				if(isset($err[1]) && $err[1] > 0) throw new Exception('Update Failed ['.print_r($err,true).']');
			}
            return FALSE;
        }
    }
    
    public function delete($table, array $matches) {
        $matches = self::clean($matches);
        $sql = 'DELETE FROM '.$table.' WHERE';
        $rc = count($matches);
        $j = 0;
        foreach ($matches as $field => $val) {
            $sql .= " ".$field." = $val ";
            if(($j+1) < $rc) $sql .= 'AND';
            $j++;
        }
        if(!($stmt = self::prepare($sql))) throw new Exception('DB Failed [prepare statement initialization failed]');
        $stmt->execute();
        $affected = $stmt->rowCount();
        if($affected > 0) {
            return $affected;
        } else {
			if($err = $stmt->errorInfo()) {
				if(isset($err[1]) && $err[1] > 0) throw new Exception('Delete Failed ['.print_r($err,true).']');
			}
            return FALSE;
        }
    }
	
	public function tableDesc($table) {
		if($res = self::query("DESC $table")) return $res;
		return FALSE;
	}
	
	public function getPrimaryKey($table) {
		$tableDesc = self::tableDesc($table);
		foreach($tableDesc as $key => $val) if($val['Key'] == 'PRI') return $val['Field'];
		return FALSE;
	}
	
	public function getForeignKey($table,$pkey) {
		$tableDesc = self::tableDesc($table);
		foreach($tableDesc as $key => $val) if($val['Key'] == 'MUL' && $val['Field'] == $pkey) return $val['Field'];
		return FALSE;
	}
	
	public function fetchFields($table) {
		if($res = self::tableDesc($table)) {
			foreach($res as $field) $fields[] = $field['Field'];
			return $fields;
		}
		return FALSE;
	}
    
    public function lastInsertedID() {
        if($res = self::query('SELECT LAST_INSERT_ID() as id')) return $res['id'];
        return FALSE;
    }

    public function transaction($params) {
        switch($params) {
            case 'begin':
                self::beginTransaction();
            break;
            case 'commit':
                self::commit();
            break;
            case 'rollback':
                self::rollBack();
            break;
        }
    }
    
}
?>
